// 1.深度优先遍历
function dfs(trees, nodes=[]) {
  if (!trees) return []
  nodes.push(trees)
  let children = trees.children
  for (let item of children) {
    dfs(item, nodes)
  }
  return nodes
}

// 2.广度优先遍历
function bfs(trees) {
  if (!trees) return []
  let queue = []
  let nodes = []
  queue.push(trees)
  while (queue.length > 0) {
    let node = queue.shift()
    nodes.push(node)
    for (let item of node.children) {
      queue.push(item)
    }
  }
  return nodes
}

// 3.深度优先深拷贝
function dfsDeepClone(value) {
  if (typeof value !== 'object') return value
  if (value instanceof Function) return eval('(' + value.toString() + ')')
  if (value instanceof RegExp) return new RegExp(value)
  if (value instanceof Date) return new Date(value)

  let instance = new value.constructor
  for (let key in value) {
    if (value.hasOwnProperty(key)) {
      instance[key] = dfsDeepClone(value[key])
    }
  }
  return instance
}

// 数组flatten 递归
function flatten(arr) {
  let ans = []
  function fn (array) {
    for (let item of array) {
      if (Array.isArray(item)) {
        ans.concat(fn(item))
      } else {
        ans.push(item)
      }
    }
  }
  fn(arr)
  return ans
}

// 数组flatten 迭代
function flatten(arr) {
  let ans = []
  let newArr = [...arr]
  while(newArr.length) {
    let item = newArr.shift()
    if (Array.isArray(item)) {
      newArr.unshift(...item)
    } else {
      ans.push(item)
    }
  }
  return ans
}

// LazyManClass
class LazyManClass {
  constructor(name) {
    console.log(`this is ${name}`);
    this.taskList = []
    setTimeout(() => {
      this.next()
    }, 0);
  }
  eat(food) {
    let self = this
    let fn = (function(food) {
      return function () {
        console.log(`eat${food}`);
        that.next();
      }
    })(food)
    this.taskList.push(fn)
    return this
  }
  sleep(seconds) {
    let self = this
    let fn = (function(seconds) {
      return function () {
        setTimeout(() => {
          console.log(`sleep${seconds}`);
          that.next();
        }, timeout);
      }
    })(seconds)
    this.taskList.push(fn)
    return this
  }
  next() {
    fn = this.taskList.shift()
    fn && fn()
  }
}